package com.own.component.netty.core;

import com.own.component.netty.constant.ConstantCommon;
import com.own.component.netty.handler.MethodMap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;

/**
 * WebSocketStarter
 *
 * @author chenxueli
 * @date 2021/4/9 10:35
 */
@Slf4j
@Component
public class NettyStarter implements ApplicationListener<ContextRefreshedEvent> {

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        // 根容器为Spring容器
        if (event.getApplicationContext().getParent() == null) {
            var beans = event.getApplicationContext().getBeansWithAnnotation(RequestMapping.class);
            beans.forEach((key, bean) -> {
                var annotation = AnnotationUtils.findAnnotation(bean.getClass(), RequestMapping.class);
                var pathSet = new HashSet<String>();
                if (null != annotation && annotation.path().length > 0) {
                    // 开始遍历数据
                    for (var path : annotation.path()) {
                        if (path != null && path.startsWith(ConstantCommon.WEBSOCKET)) {
                            pathSet.add(path.replace(ConstantCommon.WEBSOCKET, ""));
                        }
                    }
                }
                var map = new HashMap<String, Method>(16);
                if (pathSet.size() > 0) {
                    // 获取方法下的内容
                    var methods = bean.getClass().getMethods();
                    for (var method : methods) {
                        // findAnnotation也可以拿到其父类是否包含该注解
                        if (null != method) {
                            {
                                var pathAnnotation = AnnotationUtils.findAnnotation(method, GetMapping.class);
                                if (null != pathAnnotation && pathAnnotation.path().length > 0) {
                                    // 开始遍历数据
                                    for (var methodPath : pathAnnotation.path()) {
                                        pathSet.forEach(path -> map.put(path + (methodPath.startsWith("/") ? "" : "/") + methodPath, method));
                                    }
                                }
                            }
                            {
                                var pathAnnotation = AnnotationUtils.findAnnotation(method, PostMapping.class);
                                if (null != pathAnnotation && pathAnnotation.path().length > 0) {
                                    // 开始遍历数据
                                    for (var methodPath : pathAnnotation.path()) {
                                        pathSet.forEach(path -> map.put(path + (methodPath.startsWith("/") ? "" : "/") + methodPath, method));
                                    }
                                }
                            }
                            {
                                var pathAnnotation = AnnotationUtils.findAnnotation(method, PutMapping.class);
                                if (null != pathAnnotation && pathAnnotation.path().length > 0) {
                                    // 开始遍历数据
                                    for (var methodPath : pathAnnotation.path()) {
                                        pathSet.forEach(path -> map.put(path + (methodPath.startsWith("/") ? "" : "/") + methodPath, method));
                                    }
                                }
                            }
                            {
                                var pathAnnotation = AnnotationUtils.findAnnotation(method, DeleteMapping.class);
                                if (null != pathAnnotation && pathAnnotation.path().length > 0) {
                                    // 开始遍历数据
                                    for (var methodPath : pathAnnotation.path()) {
                                        pathSet.forEach(path -> map.put(path + (methodPath.startsWith("/") ? "" : "/") + methodPath, method));
                                    }
                                }
                            }
                        }
                    }
                }
                MethodMap.add(bean, map);
                log.info("websocket:key:{},bean:{}", key, bean.getClass().getName());
            });
        }
    }

}
